#ifndef MMU_H
#define MMU_H

#include "comm/types.h"
#include "comm/cpu_instr.h"

#define PDE_CNT 1024

#define PTE_P (1 << 0)
#define PDE_P (1 << 0)
#define PDE_W (1 << 1)
#define PTE_W (1 << 1)
#define PDE_U (1 << 2)

/**
 * 页目录项PDE
 */
typedef union _PDE_T {
    uint32_t v;
    struct {
        uint32_t P   : 1;
        uint32_t RW  : 1;
        uint32_t US  : 1;
        uint32_t PWT : 1;
        uint32_t PCD : 1;
        uint32_t A   : 1;
        uint32_t     : 1;
        uint32_t PS  : 1;
        uint32_t     : 4;
        uint32_t PHY_PT_ADDR: 20;
    };
} PDE_T;

/**
 * 页表项PTE
 */
typedef union _PTE_T {
    uint32_t v;
    struct {
        uint32_t P   : 1;
        uint32_t RW  : 1;
        uint32_t US  : 1;
        uint32_t PWT : 1;
        uint32_t PCD : 1;
        uint32_t A   : 1;
        uint32_t D   : 1;
        uint32_t PAT : 1;
        uint32_t G   : 1;
        uint32_t     : 3;
        uint32_t PHY_PAGE_ADDR: 20;
    };
} PTE_T;

static inline void mmu_set_page_dir(uint32_t paddr)
{
    write_cr3(paddr);
}

static inline uint32_t pde_index(uint32_t vaddr)
{
    return vaddr >> 22;
}

static inline uint32_t pte_index(uint32_t vaddr)
{
    return (vaddr >> 12) & 0x000003FF;  // 右移12位并将高10位清0
}

static inline uint32_t pde_paddr(PDE_T *pde)
{
    return pde->PHY_PT_ADDR << 12;
}
static inline uint32_t pte_paddr(PTE_T *pte)
{
    return pte->PHY_PAGE_ADDR << 12;
}

#endif